#ifndef __HELPER_CUDA_H__
#define __HELPER_CUDA_H__

#include <helper_maca.h>
#include <samples_cuda_to_maca_adaptor.h>

// Beginning of GPU Architecture definitions
inline int _ConvertSMVer2Cores(int major, int minor) {
  // Defines for GPU Architecture types (using the SM version to determine
  // the # of cores per SM
  typedef struct {
    int SM;  // 0xMm (hexidecimal notation), M = SM Major version,
    // and m = SM minor version
    int Cores;
  } sSMtoCores;

  sSMtoCores nGpuArchCoresPerSM[] = {
      {0x70,  64},
      {0x75,  64},
      {0x80,  64},
      {-1, -1}};

  int index = 0;

  while (nGpuArchCoresPerSM[index].SM != -1) {
    if (nGpuArchCoresPerSM[index].SM == ((major << 4) + minor)) {
      return nGpuArchCoresPerSM[index].Cores;
    }

    index++;
  }

  // If we don't find the values, we default use the previous one
  // to run properly
  printf(
      "MapSMtoCores for SM %d.%d is undefined."
      "  Default to use %d Cores/SM\n",
      major, minor, nGpuArchCoresPerSM[index - 1].Cores);
  return nGpuArchCoresPerSM[index - 1].Cores;
}

#ifdef CUDA_DRIVER_API
static const char *__mcGetErrorName(mcDrvError_t error)
{
    switch (error)
    {
    case MC_SUCCESS:
        return "MACA_SUCCESS";
    case MC_ERROR_INVALID_VALUE:
        return "MACA_ERROR_INVALID_VALUE";
    case MC_ERROR_OUT_OF_MEMORY:
        return "MACA_ERROR_OUT_OF_MEMORY";
    case MC_ERROR_NOT_INITIALIZED:
        return "MACA_ERROR_NOT_INITIALIZED";
    case MC_ERROR_DEINITIALIZED:
        return "MACA_ERROR_DEINITIALIZED";
    case MC_ERROR_PROFILER_DISABLED:
        return "MACA_ERROR_PROFILER_DISABLED";
    case MC_ERROR_PROFILER_NOT_INITIALIZED:
        return "MACA_ERROR_PROFILER_NOT_INITIALIZED";
    case MC_ERROR_PROFILER_ALREADY_STARTED:
        return "MACA_ERROR_PROFILER_ALREADY_STARTED";
    case MC_ERROR_PROFILER_ALREADY_STOPPED:
        return "MACA_ERROR_PROFILER_ALREADY_STOPPED";
    case MC_ERROR_STUB_LIBRARY:
        return "MACA_ERROR_STUB_LIBRARY";
    case MC_ERROR_NO_DEVICE:
        return "MACA_ERROR_NO_DEVICE";
    case MC_ERROR_INVALID_DEVICE:
        return "MACA_ERROR_INVALID_DEVICE";
    case MC_ERROR_DEVICE_NOT_LICENSED:
        return "MACA_ERROR_DEVICE_NOT_LICENSED";
    case MC_ERROR_INVALID_IMAGE:
        return "MACA_ERROR_INVALID_IMAGE";
    case MC_ERROR_INVALID_CONTEXT:
        return "MACA_ERROR_INVALID_CONTEXT";
    case MC_ERROR_CONTEXT_ALREADY_CURRENT:
        return "MACA_ERROR_CONTEXT_ALREADY_CURRENT";
    case MC_ERROR_MAP_FAILED:
        return "MACA_ERROR_MAP_FAILED";
    case MC_ERROR_UNMAP_FAILED:
        return "MACA_ERROR_UNMAP_FAILED";
    case MC_ERROR_ARRAY_IS_MAPPED:
        return "MACA_ERROR_ARRAY_IS_MAPPED";
    case MC_ERROR_ALREADY_MAPPED:
        return "MACA_ERROR_ALREADY_MAPPED";
    case MC_ERROR_NO_BINARY_FOR_GPU:
        return "MACA_ERROR_NO_BINARY_FOR_GPU";
    case MC_ERROR_ALREADY_ACQUIRED:
        return "MACA_ERROR_ALREADY_ACQUIRED";
    case MC_ERROR_NOT_MAPPED:
        return "MACA_ERROR_NOT_MAPPED";
    case MC_ERROR_NOT_MAPPED_AS_ARRAY:
        return "MACA_ERROR_NOT_MAPPED_AS_ARRAY";
    case MC_ERROR_NOT_MAPPED_AS_POINTER:
        return "MACA_ERROR_NOT_MAPPED_AS_POINTER";
    case MC_ERROR_ECC_UNCORRECTABLE:
        return "MACA_ERROR_ECC_UNCORRECTABLE";
    case MC_ERROR_UNSUPPORTED_LIMIT:
        return "MACA_ERROR_UNSUPPORTED_LIMIT";
    case MC_ERROR_CONTEXT_ALREADY_IN_USE:
        return "MACA_ERROR_CONTEXT_ALREADY_IN_USE";
    case MC_ERROR_PEER_ACCESS_UNSUPPORTED:
        return "MACA_ERROR_PEER_ACCESS_UNSUPPORTED";
    case MC_ERROR_INVALID_KERNEL_FILE:
        return "MACA_ERROR_INVALID_PTX";
    case MC_ERROR_INVALID_GRAPHICS_CONTEXT:
        return "MACA_ERROR_INVALID_GRAPHICS_CONTEXT";
    case MC_ERROR_MXLINK_UNCORRECTABLE:
        return "MACA_ERROR_NVLINK_UNCORRECTABLE";
    case MC_ERROR_JIT_COMPILER_NOT_FOUND:
        return "MACA_ERROR_JIT_COMPILER_NOT_FOUND";
    case MC_ERROR_UNSUPPORTED_KERNEL_VERSION:
        return "MACA_ERROR_UNSUPPORTED_PTX_VERSION";
    case MC_ERROR_JIT_COMPILATION_DISABLED:
        return "MACA_ERROR_JIT_COMPILATION_DISABLED";
    case MC_ERROR_UNSUPPORTED_EXEC_AFFINITY:
        return "MACA_ERROR_UNSUPPORTED_EXEC_AFFINITY";
    case MC_ERROR_INVALID_SOURCE:
        return "MACA_ERROR_INVALID_SOURCE";
    case MC_ERROR_FILE_NOT_FOUND:
        return "MACA_ERROR_FILE_NOT_FOUND";
    case MC_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND:
        return "MACA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND";
    case MC_ERROR_SHARED_OBJECT_INIT_FAILED:
        return "MACA_ERROR_SHARED_OBJECT_INIT_FAILED";
    case MC_ERROR_OPERATING_SYSTEM:
        return "MACA_ERROR_OPERATING_SYSTEM";
    case MC_ERROR_INVALID_HANDLE:
        return "MACA_ERROR_INVALID_HANDLE";
    case MC_ERROR_ILLEGAL_STATE:
        return "MACA_ERROR_ILLEGAL_STATE";
    case MC_ERROR_NOT_FOUND:
        return "MACA_ERROR_NOT_FOUND";
    case MC_ERROR_NOT_READY:
        return "MACA_ERROR_NOT_READY";
    case MC_ERROR_ILLEGAL_ADDRESS:
        return "MACA_ERROR_ILLEGAL_ADDRESS";
    case MC_ERROR_LAUNCH_OUT_OF_RESOURCES:
        return "MACA_ERROR_LAUNCH_OUT_OF_RESOURCES";
    case MC_ERROR_LAUNCH_TIMEOUT:
        return "MACA_ERROR_LAUNCH_TIMEOUT";
    case MC_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING:
        return "MACA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING";
    case MC_ERROR_PEER_ACCESS_ALREADY_ENABLED:
        return "MACA_ERROR_PEER_ACCESS_ALREADY_ENABLED";
    case MC_ERROR_PEER_ACCESS_NOT_ENABLED:
        return "MACA_ERROR_PEER_ACCESS_NOT_ENABLED";
    case MC_ERROR_PRIMARY_CONTEXT_ACTIVE:
        return "MACA_ERROR_PRIMARY_CONTEXT_ACTIVE";
    case MC_ERROR_CONTEXT_IS_DESTROYED:
        return "MACA_ERROR_CONTEXT_IS_DESTROYED";
    case MC_ERROR_ASSERT:
        return "MACA_ERROR_ASSERT";
    case MC_ERROR_TOO_MANY_PEERS:
        return "MACA_ERROR_TOO_MANY_PEERS";
    case MC_ERROR_HOST_MEMORY_ALREADY_REGISTERED:
        return "MACA_ERROR_HOST_MEMORY_ALREADY_REGISTERED";
    case MC_ERROR_HOST_MEMORY_NOT_REGISTERED:
        return "MACA_ERROR_HOST_MEMORY_NOT_REGISTERED";
    case MC_ERROR_HARDWARE_STACK_ERROR:
        return "MACA_ERROR_HARDWARE_STACK_ERROR";
    case MC_ERROR_ILLEGAL_INSTRUCTION:
        return "MACA_ERROR_ILLEGAL_INSTRUCTION";
    case MC_ERROR_MISALIGNED_ADDRESS:
        return "MACA_ERROR_MISALIGNED_ADDRESS";
    case MC_ERROR_INVALID_ADDRESS_SPACE:
        return "MACA_ERROR_INVALID_ADDRESS_SPACE";
    case MC_ERROR_INVALID_PC:
        return "MACA_ERROR_INVALID_PC";
    case MC_ERROR_LAUNCH_FAILED:
        return "MACA_ERROR_LAUNCH_FAILED";
    case MC_ERROR_COOPERATIVE_LAUNCH_TOO_LARGE:
        return "MACA_ERROR_COOPERATIVE_LAUNCH_TOO_LARGE";
    case MC_ERROR_NOT_PERMITTED:
        return "MACA_ERROR_NOT_PERMITTED";
    case MC_ERROR_NOT_SUPPORTED:
        return "MACA_ERROR_NOT_SUPPORTED";
    case MC_ERROR_SYSTEM_NOT_READY:
        return "MACA_ERROR_SYSTEM_NOT_READY";
    case MC_ERROR_SYSTEM_DRIVER_MISMATCH:
        return "MACA_ERROR_SYSTEM_DRIVER_MISMATCH";
    case MC_ERROR_COMPAT_NOT_SUPPORTED_ON_DEVICE:
        return "MACA_ERROR_COMPAT_NOT_SUPPORTED_ON_DEVICE";
    case MC_ERROR_MPS_CONNECTION_FAILED:
        return "MACA_ERROR_MPS_CONNECTION_FAILED";
    case MC_ERROR_MPS_RPC_FAILURE:
        return "MACA_ERROR_MPS_RPC_FAILURE";
    case MC_ERROR_MPS_SERVER_NOT_READY:
        return "MACA_ERROR_MPS_SERVER_NOT_READY";
    case MC_ERROR_MPS_MAX_CLIENTS_REACHED:
        return "MACA_ERROR_MPS_MAX_CLIENTS_REACHED";
    case MC_ERROR_MPS_MAX_CONNECTIONS_REACHED:
        return "MACA_ERROR_MPS_MAX_CONNECTIONS_REACHED";
    case MC_ERROR_STREAM_CAPTURE_UNSUPPORTED:
        return "MACA_ERROR_STREAM_CAPTURE_UNSUPPORTED";
    case MC_ERROR_STREAM_CAPTURE_INVALIDATED:
        return "MACA_ERROR_STREAM_CAPTURE_INVALIDATED";
    case MC_ERROR_STREAM_CAPTURE_MERGE:
        return "MACA_ERROR_STREAM_CAPTURE_MERGE";
    case MC_ERROR_STREAM_CAPTURE_UNMATCHED:
        return "MACA_ERROR_STREAM_CAPTURE_UNMATCHED";
    case MC_ERROR_STREAM_CAPTURE_UNJOINED:
        return "MACA_ERROR_STREAM_CAPTURE_UNJOINED";
    case MC_ERROR_STREAM_CAPTURE_ISOLATION:
        return "MACA_ERROR_STREAM_CAPTURE_ISOLATION";
    case MC_ERROR_STREAM_CAPTURE_IMPLICIT:
        return "MACA_ERROR_STREAM_CAPTURE_IMPLICIT";
    case MC_ERROR_CAPTURED_EVENT:
        return "MACA_ERROR_CAPTURED_EVENT";
    case MC_ERROR_STREAM_CAPTURE_WRONG_THREAD:
        return "MACA_ERROR_STREAM_CAPTURE_WRONG_THREAD";
    case MC_ERROR_TIMEOUT:
        return "MACA_ERROR_TIMEOUT";
    case MC_ERROR_GRAPH_EXEC_UPDATE_FAILURE:
        return "MACA_ERROR_GRAPH_EXEC_UPDATE_FAILURE";
    case MC_ERROR_EXTERNAL_DEVICE:
        return "MACA_ERROR_EXTERNAL_DEVICE";
    case MC_ERROR_UNKNOWN:
        return "MACA_ERROR_UNKNOWN";
    }
    return "<unknown>";
}
#endif

#endif /*__HELPER_CUDA_H__*/